#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>
#include <error.h>
#include <pthread.h>

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavutil/file.h>

#define PORT 1077
#define TCP_BUFF 1024
#define RTP_BUFF 1024 * 64

int client_fd;
struct thread_param_struct
{
    int client_fd;
    char tcp_buf[TCP_BUFF];
    char rtp_buf[RTP_BUFF];
    int rtp_reader_index;
    int rtp_write_index;
    int is_complete;
    size_t remain_to_read;
};
//数组copy，从src往dest复制len个char数据
int copy_byte_arr(char src[], char dest[], size_t src_index, size_t dest_index, size_t len)
{
    for (size_t i = 0; i < len; i++)
    {
        dest[dest_index + i] = src[src_index + i];
    }
}
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
{   
    // 0x30, 0x31, 0x63 ....
    // i , b , p
    // AVPacket
    // AVPacket *pkt = av_packet_alloc();
    // //decode jt1078
    // pkt->data = buf;
    // pkt->pts = 

    struct thread_param_struct *bd = (struct thread_param_struct *)opaque;

    int size;
    size = read(bd->client_fd, bd->tcp_buf, TCP_BUFF);
    if (size == 0)
    {
        printf("client closed\n");
        close(bd->client_fd);
        pthread_exit(0);
    }

    copy_byte_arr(bd->tcp_buf, buf, 26, 0, size - 26);
    return size - 26;
}

void process_client(int client_fd)
{
    AVFormatContext *fmt_ctx = NULL;
    AVIOContext *avio_ctx = NULL;
    const AVCodec *codec;
    uint8_t *buffer = NULL, *avio_ctx_buffer = NULL;
    size_t buffer_size, avio_ctx_buffer_size = 2048;
    char *input_filename = NULL;
    int ret = 0;
    av_register_all();
    if (!(fmt_ctx = avformat_alloc_context()))
    {
        ret = AVERROR(ENOMEM);
        goto end;
    }

    avio_ctx_buffer = av_malloc(avio_ctx_buffer_size);
    if (!avio_ctx_buffer)
    {
        ret = AVERROR(ENOMEM);
        goto end;
    }
    struct thread_param_struct t_param;
    t_param.client_fd = client_fd;

    avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size,
                                  0, &t_param, &read_packet, NULL, NULL);
    if (!avio_ctx)
    {
        ret = AVERROR(ENOMEM);
        goto end;
    }
    fmt_ctx->pb = avio_ctx;

    ret = avformat_open_input(&fmt_ctx, NULL, NULL, NULL);
    if (ret < 0)
    {
        fprintf(stderr, "Could not open input\n");
        goto end;
    }

    // ret = avformat_find_stream_info(fmt_ctx, NULL);
    // if (ret < 0)
    // {
    //     fprintf(stderr, "Could not find stream information\n");
    //     goto end;
    // }

    //avcodec_decode_audio4
    av_dump_format(fmt_ctx, 0, NULL, 0);
    //创建packet,用于存储解码前的数据
    AVPacket *packet = (AVPacket *)malloc(sizeof(AVPacket));

    AVCodecContext *dec_ctx = NULL;

    codec = avcodec_find_decoder(AV_CODEC_ID_AAC);
    dec_ctx = avcodec_alloc_context3(codec);
    /* open it */
    if (avcodec_open2(dec_ctx, codec, NULL) < 0)
    {
        fprintf(stderr, "Could not open codec\n");
        exit(1);
    }


    AVFrame *decoded_frame = NULL;
    decoded_frame = av_frame_alloc();
    while (av_read_frame(fmt_ctx, packet) >= 0)
    {
        int ret;
        ret = avcodec_send_packet(dec_ctx, packet);

        if (ret < 0)
        {
            fprintf(stderr, "Error submitting the packet to the decoder\n");
            exit(1);
        }

        while (ret >= 0)
        {
            ret = avcodec_receive_frame(dec_ctx, decoded_frame);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
                break;
            else if (ret < 0)
            {
                fprintf(stderr, "Error during decoding\n");
                exit(1);
            }
            printf("frame data is %s\n", decoded_frame->data);
        }

        printf("got packet%s\n", packet->data);
    }

end:
    pthread_exit;
    exit(0);
}

int main()
{
    int listen_fd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in server_addr;
    bzero(&server_addr, sizeof(struct sockaddr_in)); //清零
    server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    server_addr.sin_port = htons(PORT);
    server_addr.sin_family = AF_INET;

    //绑定地址结构到套接字描述符
    if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        perror("bind error\n");
        return -1;
    }

    if (listen(listen_fd, 20) < -1)
    {
        perror("listen error\n");
    }

    while (1)
    { //接受客户端连接
        socklen_t addrlen = sizeof(struct sockaddr);
        struct sockaddr_in clientaddr; //客户端地址结构

        client_fd = accept(listen_fd, (struct sockaddr *)&clientaddr, &addrlen);

        if (client_fd < 0)
        {
            perror("accept error");
            return -1;
        }
        printf("accept success\n");

        pthread_t pid;

        if (pthread_create(&pid, NULL, process_client, client_fd) < 0)
        {
            printf("pthread create error\n");
        }
    }
    close(listen_fd);
}